<?php
/*
 Copyright (C) 2004 Renato Coelho
 (PHP)Source 2 Doc v0.5.0
 This is a simple script created in order to update the HTML2FPDF page
 It should make a php class documentation
 LICENSE: Freeware.
 Lacks: html_decode and the likes
 Plans: make an independent table for each part?

 Usage:

 require_once('source2doc.php');
 echo source2doc('filename.php'); //Print doc info on browser

 HOW TO declare var types and HOW TO use @return and @desc: (//! is a one-line comment)

 var $name; //! type

 function name()
 {
 //! @return void
 //! @desc Say something in one line, but dont use tags or ';' here
 //! @desc Fale algo em uma linha, mas nao use tags ou ';' aqui
 ...}

*/

function source2doc( $filename )
{
	define( 'endl', "\n" );
	$classname = '';
	$extends = '';

	$file = fopen( $filename, "r" );
	$tamarquivo = filesize( $filename );
	$buffer = fread( $file, $tamarquivo );
	fclose( $file );
	// //
	// Remove all PHP comments
	// Leave only the special comments '//!'
	// //
	// Remove /* multi-line comments */
	$regexp = '|/\\*.*?\\*/|s';
	$buffer = preg_replace( $regexp, '', $buffer );
	// Remove // one line comments
	$regexp = '|//[^!].*|m';
	$buffer = preg_replace( $regexp, '', $buffer );
	// //
	// Get class name and what it extends (or not)
	// //
	$regexp = '|class\\s+?(\\S+)(\\s+?\\S+\\s+?(\\S+))?|mi';
	preg_match( $regexp, $buffer, $aux ); //one class per source file
	$classname = $aux[1];
	if ( !empty( $aux[3] ) ) $extends = $aux[3];
	else $extends = '';

	$html = '<b>CLASSNAME:</b> ' . $classname . '<br />' . endl;
	if ( $extends != '' ) $html .= '<b>EXTENDS:</b> ' . $extends . '<br />' . endl;
	$html .= '<table border="1" width="100%">' . endl;
	// //
	// Get constants from source code
	// //
	$html .= '<tr>' . endl;
	$html .= '<th bgcolor="#6191ff" colspan="2">' . endl;
	$html .= 'CONSTANTS' . endl;
	$html .= '</th>' . endl;
	$html .= '</tr>' . endl;

	$regexp = '/define[(](.*?);/si';
	preg_match_all( $regexp, $buffer, $const );

	$const = $const[0];
	for( $i = 0; $i < count( $const ) ; $i++ ) {
		$html .= '<tr>' . endl;
		$html .= '<td colspan="2">' . endl;
		$html .= '<font size=2>' . $const[$i] . '</font>' . endl;
		$html .= '</td>' . endl;
		$html .= '</tr>' . endl;
	}
	// //
	// Get imports from source code
	// //
	$html .= '<tr>' . endl;
	$html .= '<th bgcolor="#6191ff" colspan="2">' . endl;
	$html .= 'IMPORTS' . endl;
	$html .= '</th>' . endl;
	$html .= '</tr>' . endl;

	$regexp = '/((require|include)[(_].*?);/si';
	preg_match_all( $regexp, $buffer, $imports );

	$imports = $imports[0];
	for( $i = 0; $i < count( $imports ) ; $i++ ) {
		$html .= '<tr>' . endl;
		$html .= '<td colspan="2">' . endl;
		$html .= '<font size=2>' . $imports[$i] . '</font>' . endl;
		$html .= '</td>' . endl;
		$html .= '</tr>' . endl;
	}
	// //
	// Get attributes from class
	// //
	$html .= '<tr>' . endl;
	$html .= '<th bgcolor="#6191ff" colspan="2">' . endl;
	$html .= 'ATTRIBUTES' . endl;
	$html .= '</th>' . endl;
	$html .= '</tr>' . endl;

	$regexp = '|var\\s(.+);\\s*(//!\\s*?(\\S+))?|mi';
	preg_match_all( $regexp, $buffer, $atr );

	$vname = $atr[1];
	$vtype = $atr[3];

	if ( !empty( $vname ) ) {
		$html .= '<tr>' . endl;
		$html .= '<td align="center" width="10%" bgcolor="#bbbbbb">' . endl;
		$html .= 'TYPE' . endl;
		$html .= '</td>' . endl;
		$html .= '<td align="center" width="90%" bgcolor="#bbbbbb">' . endl;
		$html .= 'NAME' . endl;
		$html .= '</td>' . endl;
		$html .= '</tr>' . endl;
	}

	for( $i = 0; $i < count( $vname ) ; $i++ ) {
		$html .= '<tr>' . endl;

		$html .= '<td align="center">' . endl;
		if ( empty( $vtype[$i] ) ) $html .= '<font size=2><i>(???)</i></font>' . endl;
		else $html .= '<font size=2><i>(' . $vtype[$i] . ')</i></font>' . endl;
		$html .= '</td>' . endl;

		$html .= '<td>' . endl;
		$html .= '<font size=2><b>var</b> ' . $vname[$i] . ';</font>' . endl;
		$html .= '</td>' . endl;
		$html .= '</tr>' . endl;
	}
	// ///
	// Get class' methods
	// ///
	$html .= '<tr>' . endl;
	$html .= '<th bgcolor="#6191ff" colspan="2">' . endl;
	$html .= 'METHODS' . endl;
	$html .= '</th>' . endl;
	$html .= '</tr>' . endl;

	$regexp = '|function\\s([^)]*)[)].*?(//!.*?)*;|si';
	preg_match_all( $regexp, $buffer, $func );

	$funcname = $func[1];
	$funccomment = $func[0];

	for( $i = 0; $i < count( $funcname ) ; $i++ ) {
		$html .= '<tr>' . endl;
		$html .= '<td bgcolor="#33ff99" colspan="2">' . endl;
		$html .= '<font size=2><b>function</b> ' . $funcname[$i] . ')</font>' . endl;
		$html .= '</td>' . endl;
		$html .= '</tr>' . endl;

		$desc = '';
		$ret = '';
		$regexp = '|//!(.*)|mi';
		preg_match_all( $regexp, $funccomment[$i], $temp );
		$temp = $temp[1];

		if ( empty( $temp[0] ) ) continue;
		foreach( $temp as $val ) {
			if ( strstr( $val, '@desc' ) ) {
				$regexp = '|.*?@desc(.*)|si';
				preg_match( $regexp, $val, $temp2 );
				$desc = $temp2[1];
			} elseif ( strstr( $val, '@return' ) ) {
				$regexp = '|.*?@return(.*)|si';
				preg_match( $regexp, $val, $temp3 );
				$ret = $temp3[1];
			}
		}
		if ( $ret != '' or $desc != '' ) {
			$html .= '<tr>' . endl;
			// @return column
			$html .= '<td width="30%">' . endl;
			if ( $ret == '' ) $html .= '<font size=2><b>Return:</b> <i>?void?</i></font>' . endl;
			else $html .= '<font size=2><b>Return:</b> <i>' . trim( $ret ) . '</i></font>' . endl;
			$html .= '</td>' . endl;
			// @desc column
			$html .= '<td width="70%">' . endl;
			if ( $desc == '' ) $html .= '<font size=2><b>OBS:</b> </font>' . endl;
			else $html .= '<font size=2><b>OBS:</b> ' . trim( $desc ) . '</font>' . endl;
			$html .= '</td>' . endl;

			$html .= '</tr>' . endl;
		}
	}
	// ///
	$html .= '</table>';

	return $html;
}

?>